package com.dongjiantong.openplatform.utils;

import com.dongjiantong.openplatform.entity.OPUploadFile;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Defaults;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.primitives.Primitives;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author cao
 * @create 2017-12-14 上午9:28
 **/
public class OPParameterResolver {
    private static final Logger log = LoggerFactory.getLogger(OPParameterResolver.class);
    private static final DefaultConversionService converter = new DefaultConversionService();
    private static final ObjectMapper objectMapper = new ObjectMapper();

    public OPParameterResolver() {
    }

    public static Object resolve(Class<?> paramType, String paramName, Map<String, Object> context) throws Exception {
        if(paramType.isAssignableFrom(Map.class)) {
            return context;
        } else {
            Object realParam;
            if(!Primitives.isWrapperType(paramType) && !Primitives.allPrimitiveTypes().contains(paramType) && paramType != String.class) {
                Iterator formNames;
                MultipartHttpServletRequest request;
                if(paramType == MultipartFile.class) {
                    request = (MultipartHttpServletRequest)context.get("request");
                    formNames = request.getFileNames();
                    if(formNames.hasNext()) {
                        return request.getFile((String)formNames.next());
                    }
                }

                if(paramType == OPUploadFile.class) {
                    request = (MultipartHttpServletRequest)context.get("request");
                    formNames = request.getFileNames();
                    LinkedHashMap mappedFiles = Maps.newLinkedHashMap();

                    while(formNames.hasNext()) {
                        List<MultipartFile> multipartFiles = Lists.newArrayList();
                        String formName = (String)formNames.next();
                        List<MultipartFile> files = request.getFiles(formName);
                        Iterator var9 = files.iterator();

                        while(var9.hasNext()) {
                            MultipartFile file = (MultipartFile)var9.next();
                            multipartFiles.add(file);
                        }

                        mappedFiles.put(formName, multipartFiles);
                    }

                    return new OPUploadFile(mappedFiles);
                } else if(paramType.isAssignableFrom(context.get(paramName).getClass())) {
                    return context.get(paramName);
                } else {
                    if(context.containsKey(paramName) && context.get(paramName) instanceof String) {
                        try {
                            return objectMapper.readValue(String.valueOf(context.get(paramName)), paramType);
                        } catch (Exception var11) {
                            log.error("failed to parse {} to {} use jackson, cause:{}", new Object[]{context.get(paramName), paramType, Throwables.getStackTraceAsString(var11)});
                        }
                    }

                    realParam = BeanUtils.instantiate(paramType);
                    org.apache.commons.beanutils.BeanUtils.populate(realParam, context);
                    return realParam;
                }
            } else {
                realParam = context.get(paramName);
                if(realParam == null) {
                    realParam = Defaults.defaultValue(paramType);
                }

                return converter.convert(realParam, paramType);
            }
        }
    }
}

